﻿/****************************** Module Header ******************************\
Module Name:    MessageMatchCount.cs
Project:        SQL Server Error Log Parsing module

A class that represents the number of times that a given SQL Server system 
system message has been parsed out of a SQL Server error log.

This source is subject to the Microsoft Public License.
See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
All other rights reserved.

THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;

namespace SQLServerSleuth.PowerShell.Commands.ParseERRORLOG
{
    /// <summary>
    /// The MessageMatchCount class represents the number of times that a 
    /// given SQL Server system system message has been parsed out of a 
    /// SQL Server error log.
    /// </summary>
    public class MessageMatchCount
    {
        /// <summary>
        /// The solitary constructor for the class assigns the given values 
        /// to the public fields.
        /// </summary>
        /// <param name="MessageID">The ID of the corresponding SQL Server 
        /// system message.</param>
        /// <param name="CurrentLogFileMatchCount">The number of times that 
        /// the system message was found in the current SQL Server error log 
        /// file.</param>
        /// <param name="HistoricalMatchCount">The number of times that 
        /// the system message was found in one or more SQL Server error log 
        /// files.</param>
        public MessageMatchCount
        (
            int MessageID,
            int CurrentLogFileMatchCount,
            int HistoricalMatchCount
        )
        {
            this.CurrentLogFileMatchCount = CurrentLogFileMatchCount;
            this.HistoricalMatchCount = HistoricalMatchCount;
            this.MessageID = MessageID;

            return;
        }

        /// <summary>
        /// See the corresponding parameter of the <see cref="MessageMatchCount"/> constructor.
        /// </summary>
        public int CurrentLogFileMatchCount = 0;

        /// <summary>
        /// See the corresponding parameter of the <see cref="MessageMatchCount"/> constructor.
        /// </summary>
        public int HistoricalMatchCount = 0;

        /// <summary>
        /// See the corresponding parameter of the <see cref="MessageMatchCount"/> constructor.
        /// </summary>
        public int MessageID = 0;
    }

    /// <summary>
    /// The MessageMatchCounts class is simply a collection of 
    /// MessageMatchCount objects.  By inheriting from the List(Of T) class 
    /// (the generic equivalent of the System.Collections.ArrayList class) 
    /// we end up with a strongly typed list of MessageMatchCount objects.
    /// </summary>
    public class MessageMatchCounts : List<MessageMatchCount>
    {
        /// <summary>
        /// The single, default constructor simply calls the base 
        /// constructor.
        /// </summary>
        public MessageMatchCounts() : base()
        {
            return;
        }

        /// <summary>
        /// This is the default Comparer for MessageMatchCount objects, 
        /// which is used to sort a collection of MessageMatchCount objects 
        /// in descending order based on the current and historical match 
        /// count values.
        /// </summary>
        /// <param name="item1">The first MessageMatchCount object.</param>
        /// <param name="item2">The second MessageMatchCount object.</param>
        /// <returns>The values is zero if the objects are equal, -1 if the 
        /// first object is greater, and 1 if the second object is greater.</returns>
        protected static int compareMatchCountObjects
        (
            MessageMatchCount item1,
            MessageMatchCount item2
        )
        {
            int returnValue = 0;

            int combinedCounts_item1 = 0;
            int combinedCounts_item2 = 0;

            if (null == item1)
            {
                if (null == item2)
                {
                    //  Both objects are null, so they are equal.
                    returnValue = 0;
                }
                else
                {
                    //  The first object is null but the second isn't, so 
                    //  the latter is greater.
                    returnValue = 1;
                }
            }
            else
            {
                if (null == item2)
                {
                    //  The second object is null but the first isn't, so 
                    //  the first is greater.
                    returnValue = -1;
                }
                else
                {
                    //  Begin by summing the number of matches, both current 
                    //  and historical, for each object.
                    combinedCounts_item1 = item1.CurrentLogFileMatchCount + item1.HistoricalMatchCount;
                    combinedCounts_item2 = item2.CurrentLogFileMatchCount + item2.HistoricalMatchCount;

                    if (combinedCounts_item1 > combinedCounts_item2)
                    {
                        //  Determine the greater object based solely on the 
                        //  combined match counts.
                        returnValue = -1;
                    }
                    else if (combinedCounts_item1 < combinedCounts_item2)
                    {
                        //  Determine the greater object based solely on the 
                        //  combined match counts.
                        returnValue = 1;
                    }
                    else
                    {
                        //  Since the combined match counts are equal, the 
                        //  comparison falls to the ordinal value of the two 
                        //  message ID values.
                        //  NOTE: This isn't strictly necessary, but it does 
                        //  add a deterministic quality to sorting the same 
                        //  list of MessageMatchCount objects.
                        returnValue = (item1.MessageID.CompareTo(item2.MessageID));
                    }
                }
            }

            return returnValue;
        }

        /// <summary>
        /// This method clears the current match count value of each item in 
        /// the list, which is done for each new SQL Server error log to be 
        /// parsed.
        /// </summary>
        public void ResetCurrentMatchCounts()
        {
            foreach (MessageMatchCount messageMatchCount in this)
            {
                messageMatchCount.CurrentLogFileMatchCount = 0;
            }

            return;
        }

        /// <summary>
        /// This method sorts the contents of the list, using the default 
        /// Comparer, in descending order of matches (and ascending order of 
        /// message IDs if there are match count ties).
        /// NOTE: For improved efficiency, the dictionary of MessageTemplate 
        /// objects isn't sorted, the list of MessageMatchCounts, a lighter 
        /// weight collection) is instead.
        /// </summary>
        public new void Sort()
        {
            base.Sort(MessageMatchCounts.compareMatchCountObjects);

            return;
        }
    }
}
